package com.csun.cmny.provider.service.impl;

import com.csun.cmny.base.enums.ErrorCodeEnum;
import com.csun.cmny.core.support.BaseService;
import com.csun.cmny.provider.dao.*;
import com.csun.cmny.provider.device.phone.PhoneMessageHandler;
import com.csun.cmny.provider.device.phone.entity.PhoneDataEntity;
import com.csun.cmny.provider.exceptions.DmcBizException;
import com.csun.cmny.provider.model.domain.DmcDevice;
import com.csun.cmny.provider.model.domain.DmcPhoneData;
import com.csun.cmny.provider.model.domain.DmcPhoneLocation;
import com.csun.cmny.provider.model.dto.phone.BindPhoneLocationDto;
import com.csun.cmny.provider.model.dto.phone.PhonePageQuery;
import com.csun.cmny.provider.model.dto.propertyManagement.SelectDeviceDataDto;
import com.csun.cmny.provider.model.enums.phone.DmcPhoneLocationBindTypeEnum;
import com.csun.cmny.provider.model.vo.DmcPhoneVo;
import com.csun.cmny.provider.model.vo.RoomBuildingVo;
import com.csun.cmny.provider.model.vo.propertyManagement.PropertyDataVo;
import com.csun.cmny.provider.resolver.CmnyMessageSource;
import com.csun.cmny.provider.service.*;
import com.csun.cmny.util.PubUtils;
import com.csun.cmny.util.PublicUtil;
import com.csun.cmny.util.RedisKeyUtil;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.base.Preconditions;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.List;

/**
 * @Auther: chisj chisj@foxmal.com
 * @Date: 2019-02-11 14:54
 * @Description: the class dmc phone location service impl
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class DmcPhoneLocationServiceImpl extends BaseService<DmcPhoneLocation>
        implements DmcPhoneLocationService {

    @Resource
    private OmcRpcService omcRpcService;
    @Resource
    private DmcDeviceService dmcDeviceService;
    @Resource
    private CmnyMessageSource cmnyMessageSource;
    @Resource
    private DmcPhoneLocationMapper dmcPhoneLocationMapper;
    @Resource
    private DmcPhoneDataService dmcPhoneDataService;
    @Resource
    private DmcPhoneDataHiService dmcPhoneDataHiService;
    @Resource
    private DmcPhoneZoneService dmcPhoneZoneService;
    @Resource
    private DmcPhoneEventService dmcPhoneEventService;
    @Resource
    private DmcPhoneEventAlertService dmcPhoneEventAlertService;
    @Resource
    private DmcDeviceAlertService dmcDeviceAlertService;
    @Resource
    private RedisTemplate<String, Object> redisTemplate;
    @Resource
    private PhoneMessageHandler phoneMessageHandler;

    /**
     * bind phone location
     *
     * @param bindPhoneLocationDto bind phone location dto
     * @return the int.
     */
    @Override
    public Integer bindPhoneLocation(BindPhoneLocationDto bindPhoneLocationDto) {

        // 1.校验电话机
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsPhoneByDeviceId(bindPhoneLocationDto.getDeviceId());
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610023, bindPhoneLocationDto.getDeviceId());
        }

        // 2.校验电话机是否已经被绑定
        DmcPhoneLocation dmcPhoneLocationQuery = dmcPhoneLocationMapper
                .selectByPrimaryKey(bindPhoneLocationDto.getDeviceId());
        if (PublicUtil.isNotEmpty(dmcPhoneLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610022, bindPhoneLocationDto.getDeviceId(),
                    dmcPhoneLocationQuery.getLocation());
        }

        // 3.校验绑定类型
        Preconditions.checkArgument(!PubUtils.isNull(bindPhoneLocationDto.getBindType()),
                cmnyMessageSource.getMessage("phone.location.bind.type.null", null));

        Preconditions.checkArgument(bindPhoneLocationDto.getBindType() >= 0
                        && bindPhoneLocationDto.getBindType() <= 1,
                cmnyMessageSource.getMessage("phone.location.bind.type.range", null));

        // 4.校验位置
        Preconditions.checkArgument(!PubUtils.isNull(bindPhoneLocationDto.getLocation()),
                cmnyMessageSource.getMessage("phone.location.null", null));

        // 5.校验房间Id
        if (bindPhoneLocationDto.getBindType().equals(DmcPhoneLocationBindTypeEnum.ROOM.getKey())) {
            // 绑定类型为房间
            Preconditions.checkArgument(!PubUtils.isNull(bindPhoneLocationDto.getRoomId()),
                    cmnyMessageSource.getMessage("phone.location.room.id.null", null));
            // 校验房间Id是否存在
            // TODO 校验房间Id是否存在
            RoomBuildingVo roomBuildingVo = omcRpcService
                    .queryRoomBuildingByRoomId(bindPhoneLocationDto.getRoomId());
            if (PublicUtil.isEmpty(roomBuildingVo)) {
                // 房间不存在
                throw new DmcBizException(ErrorCodeEnum.DMC100610058);
            }

            bindPhoneLocationDto.setLocation(roomBuildingVo.getLocation());
        }

        // 6.添加绑定
        DmcPhoneLocation dmcPhoneLocation = new DmcPhoneLocation();
        BeanUtils.copyProperties(bindPhoneLocationDto, dmcPhoneLocation);
        Integer result = dmcPhoneLocationMapper.insertSelective(dmcPhoneLocation);

        if (result > 0) {

            // 设置redisKey
            PhoneDataEntity phoneDataEntity = new PhoneDataEntity();
            phoneDataEntity.setDeviceId(dmcDevice.getId());
            phoneDataEntity.setDeviceNo(dmcDevice.getDeviceNo());
            phoneDataEntity.setGroupId(dmcDevice.getGroupId());
            redisTemplate.opsForValue().set(RedisKeyUtil.getZnPhoneKey(dmcDevice.getDeviceNo()), phoneDataEntity);

            // 初始化数据
            DmcPhoneData dmcPhoneData = new DmcPhoneData();
            BeanUtils.copyProperties(phoneDataEntity, dmcPhoneData);
            dmcPhoneDataService.save(dmcPhoneData);
        }

        return result;
    }

    /**
     * break phone location
     *
     * @param deviceId device id
     * @return the int.
     */
    @Override
    public Integer breakPhoneLocation(Long deviceId) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsPhoneByDeviceId(deviceId);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610023, deviceId);
        }

        // 2.判断智能电话机是否已经绑定
        DmcPhoneLocation dmcPhoneLocationQuery = dmcPhoneLocationMapper
                .selectByPrimaryKey(deviceId);
        if (PublicUtil.isEmpty(dmcPhoneLocationQuery)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610024, deviceId);
        }

        // 3.解绑智能电话机
        Integer result = dmcPhoneLocationMapper.deleteByPrimaryKey(deviceId);
        if (result > 0) {
            // 4.删除智能电话机数据
            dmcPhoneDataService.deletePhoneDataByDeviceId(deviceId);

            // 5.删除智能电话机历史数据
            dmcPhoneDataHiService.deleteDmcPhoneDataHiByDeviceId(deviceId);

            // 7.删除防区
            dmcPhoneZoneService.deletePhoneZoneByDeviceId(deviceId);

            // 8.删除事件-报警
            dmcPhoneEventAlertService.deletePhoneEventAlertByDeviceId(deviceId);

            // 9.删除事件
            dmcPhoneEventService.deletePhoneEventByDeviceId(deviceId);

            // 10.删除电话机报警
            dmcDeviceAlertService.deleteByDeviceId(deviceId);

            // 11.断开netty
//            phoneMessageHandler.clear(dmcDevice.getDeviceNo());

            // 12.移除redisKey
            String redisKey = RedisKeyUtil.getZnPhoneKey(dmcDevice.getDeviceNo());
            redisTemplate.delete(redisKey);
        }

        return result;
    }

    /**
     * query phone list with page
     *
     * @param phonePageQuery phone page query
     * @return the page info.
     */
    @Override
    public PageInfo queryPhoneListWithPage(PhonePageQuery phonePageQuery) {

        PageHelper.startPage(phonePageQuery.getPageNum(), phonePageQuery.getPageSize());

        List<DmcPhoneVo> dmcPhoneVoList = dmcPhoneLocationMapper
                .queryPhoneListWithPage(phonePageQuery);

        return new PageInfo<>(dmcPhoneVoList);
    }

    /**
     * delete phone by id
     *
     * @param id id
     * @return the int.
     */
    @Override
    public Integer deletePhoneById(Long id) {

        // 1.判断设备Id是否存在
        DmcDevice dmcDevice = dmcDeviceService.checkDeviceIsPhoneByDeviceId(id);
        if (PublicUtil.isEmpty(dmcDevice)) {
            throw new DmcBizException(ErrorCodeEnum.DMC100610023, id);
        }

        // 2.判断智能电话机是否已经绑定
        DmcPhoneLocation dmcPhoneLocationQuery = dmcPhoneLocationMapper
                .selectByPrimaryKey(id);
        if (PublicUtil.isNotEmpty(dmcPhoneLocationQuery)) {
            dmcPhoneLocationMapper.deleteByPrimaryKey(id);
        }

        // 3.删除设备Id
        return dmcDeviceService.deleteDmcDeviceById(id);
    }

    @Override
    public List<PropertyDataVo> selectDeviceData(SelectDeviceDataDto selectDeviceDataDto) {
        return dmcPhoneLocationMapper.selectDeviceData(selectDeviceDataDto);
    }
}
